﻿using System;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using Tools.Common.Reflection;
using Web.App.Infrastructure.ApplicationMessages.Contracts;
using Web.App.Infrastructure.ApplicationMessages.Implementation;
using Web.App.Infrastructure.Extensions;
using Web.App.Infrastructure.Localization.Contract;
using Webshop20.Usecases.States;
using Webshop20.Usecases.States.Registration;

namespace Webshop20.Interface.MVC.Controllers
{

    delegate ActionResult HandleSystemMessageDelegate(IDomainMessage message);

    public class ControllerBase : Controller, IUseCaseStateContext
    {
        private ILocalisationService localisationService;
        protected object viewDataModel;
        protected IRegistrationState state;
        
        public ControllerBase(ILocalisationService localisationService)
        {
            this.localisationService = localisationService;
        }

        #region generic handlers

        protected ActionResult HandleSystemEvent(DomainMessageSentEventArgs args, object sender)
        {
            var failureMessage = args.SystemMessage as FailureMessage;

            foreach (var error in failureMessage.Failures)
            {
                ViewData.ModelState.AddModelError(error.FailureCode,  localisationService.GetText(error.FailureCode));
            }

            TempData["Message"] = localisationService.GetText(failureMessage.MessageKey);
            
            return View(viewDataModel);
        }

        #endregion

        protected void HandleSystemMessage(DomainMessageSentEventArgs args, object sender)
        {
           string methodName = string.Format("Handle{0}", args.SystemMessage.GetType().Name);
           var methodInfo = this.GetType().GetMethod(methodName);
           var deleg = Delegate.CreateDelegate(typeof(HandleSystemMessageDelegate), methodInfo); 
           deleg.DynamicInvoke(args.SystemMessage);
        }

        public void AddErrorMessagesToViewDataModelState(IDomainMessage domainMessage)
        {
            var failureMessage = domainMessage as FailureMessage;

            foreach (IFailure failure in failureMessage.Failures)
            {
                ViewData.ModelState.AddModelError(failure.Property, localisationService.GetText(failure.FailureCode));
            }
        }

        protected ActionResult RedirectToAction<TEntity>(Expression<Func<TEntity, object>> action)
        {
            return RedirectToAction(ReflectAbout<TEntity>.GetMethod(action).Name, typeof(TEntity).Name);
        }

        protected ActionResult RedirectToAction<TEntity>(Expression<Func<TEntity, object>> action, object actionParams)
        {
            return RedirectToAction(ReflectAbout<TEntity>.GetMethod(action).Name, typeof(TEntity).Name, actionParams);
        }

        protected void RemoveCookie(string key)
        {
            if(ControllerContext.HttpContext.Request.Cookies[key].Exists())
                ControllerContext
                    .HttpContext
                    .Response
                    .Cookies.Add(new HttpCookie(key) {  Expires = DateTime.Now.AddDays(-2)});
        }

        #region IStateContext Members

        public void ChangeState(IRegistrationState newState)
        {
            state = newState;
        }

        public object GetSessionObject(string key)
        {
            return Session[key];            
        }

        public object GetSessionObject(int index)
        {
            return Session[index];
        }

        public void SetSessionObject(string key, object value)
        {
            Session.Add(key, value);
        }

        public void SetSessionObject(int index, object value)
        {
            Session[index] = value;
        }

        #endregion
    }
}
